package com.amtf.datafile2.cfg.excel;

import java.util.ArrayList;
import java.util.List;

import org.jdom.Attribute;
import org.jdom.DataConversionException;
import org.jdom.Document;
import org.jdom.Element;

import com.amtf.datafile2.cfg.std.StdDefinitionException;
import com.amtf.datafile2.cfg.std.StdDefinitionStore;
import com.amtf.datafile2.core.excel.ExcelDataRecord;
import com.amtf.datafile2.core.txt.TxtFTAlphabet;
import com.amtf.datafile2.core.txt.TxtFTAlphabetNumeric;
import com.amtf.datafile2.core.txt.TxtFTAny;
import com.amtf.datafile2.core.txt.TxtFTNumeric;

public class ExcelDataTableDefinitionStore extends StdDefinitionStore<ExcelDataTableDefinition> {
	public static final ExcelDataTableDefinitionStore config = new ExcelDataTableDefinitionStore();
	public static final ExcelDataTableDefinition DEFAULT_EXCEL_DEFINITION = new ExcelDataTableDefinition("");

	// @Override
	// protected File[] getDefaultConfigFiles() {
	// return null;
	// }

	public static ExcelDataTableDefinition extractConfig(String defineFile) throws StdDefinitionException {
		Document doc = loadDocument(defineFile);
		return config.parse(doc, doc.getRootElement());
	}

	@Override
	public ExcelDataTableDefinition parse(Document doc, Element root) throws StdDefinitionException {
		Attribute attrib = null;
		Element recordDef = doc.getRootElement().getChild("record-definition");
		if (recordDef == null) {
			recordDef = doc.getRootElement().getChild("RecordDefinition");
			if (recordDef == null) {
				throw new StdDefinitionException("Record definition format invalid!");
			}
		}

		String name = recordDef.getAttributeValue("name");
		if (name == null || "".equals(name)) {
			throw new StdDefinitionException("Record definition name is empty!");
		}

		ExcelDataTableDefinition dataRecDef = new ExcelDataTableDefinition(name);

		attrib = recordDef.getAttribute("firstRowTitle");
		if (attrib != null) {
			try {
				dataRecDef.setFirstRowTitle(attrib.getBooleanValue());
			} catch (DataConversionException e1) {
				throw new StdDefinitionException("firstRowTitle is empty!");
			}
		}

		attrib = recordDef.getAttribute("titleAsColumnName");
		if (attrib != null) {
			try {
				dataRecDef.setTitleAsColumnName(attrib.getBooleanValue());
			} catch (DataConversionException e1) {
				throw new StdDefinitionException("titleAsColumnName is empty!");
			}
		}

		String clsName = recordDef.getAttributeValue("dataRecordClass");
		if (clsName != null && !"".equals(clsName)) {
			try {
				dataRecDef.setDataRecordClass((Class<? extends ExcelDataRecord>) Class.forName(clsName));
			} catch (ClassNotFoundException e1) {
				throw new StdDefinitionException("Error occured when new instance of DataRecord class! " + e1.getMessage());
			}
		}

		int index = 0;
		List<ExcelDataFieldDefinition> fieldDefinition = new ArrayList<ExcelDataFieldDefinition>();
		List<Element> es = recordDef.getChildren();
		for (Element e : es) {
			if (e.getName().toLowerCase().contains("column")) {
				index++;

				name = e.getAttributeValue("name");
				if (name == null || name.length() == 0) {
					name = getColumnName(index);
				}
				ExcelDataFieldDefinition fieldDef = new ExcelDataFieldDefinition(name, dataRecDef);

				try {
					fieldDef.setCheckFormat(e.getAttribute("checkFormat").getBooleanValue());
				} catch (Throwable e1) {
					fieldDef.setCheckFormat(false);
				}
				try {
					fieldDef.setAllowEmpty(e.getAttribute("allowEmpty").getBooleanValue());
				} catch (Throwable e1) {
					fieldDef.setAllowEmpty(true);
				}
				int maxLength;
				try {
					maxLength = e.getAttribute("maxLength").getIntValue();
				} catch (Throwable e1) {
					maxLength = -1;
				}
				int minLength;
				try {
					minLength = e.getAttribute("minLength").getIntValue();
				} catch (Throwable e1) {
					minLength = 0;
				}
				try {
					String valueTypeName = e.getAttribute("type").getValue();
					if ("n".equalsIgnoreCase(valueTypeName)) {
						fieldDef.setType(new TxtFTNumeric(minLength, maxLength));
					} else if ("a".equalsIgnoreCase(valueTypeName)) {
						fieldDef.setType(new TxtFTAlphabet(minLength, maxLength));
					} else if ("an".equalsIgnoreCase(valueTypeName) || "na".equalsIgnoreCase(valueTypeName)) {
						fieldDef.setType(new TxtFTAlphabetNumeric(minLength, maxLength));
					} else if ("any".equalsIgnoreCase(valueTypeName)) {
						fieldDef.setType(new TxtFTAny(minLength, maxLength));
					} else {
						fieldDef.setType(new TxtFTAny(minLength, maxLength));
					}
				} catch (Throwable e1) {
					fieldDef.setType(new TxtFTAny(minLength, maxLength));
				}

				try {
					fieldDef.setTrimValue(e.getAttribute("trimValue").getBooleanValue());
				} catch (Throwable e1) {
					fieldDef.setTrimValue(false);
				}

				fieldDefinition.add(fieldDef);
			}
		}

		dataRecDef.addFields(fieldDefinition);
		this.addConfiguration(dataRecDef);
		return dataRecDef;
	}

	private String getColumnName(int index) {
		if (index < 27) {
			return String.valueOf((char) (index + 65));
		} else {
			int x = index / 26;
			char col1 = (char) (x + 65);
			char col2 = (char) (index + 65);
			return String.valueOf(col1) + String.valueOf(col2);
		}
	}

	// @Override
	// public DefinitionStore<ExcelDataRecordDefinition> loadConfig(String defineFile) throws DefinitionException {
	// DefinitionStore.loadConfig(config, defineFile);
	// return config;
	// }
}
